package com.faxsun.web.controller.news;

import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import mblog.web.controller.BaseController;
import mblog.web.interceptor.LiveWechatInterceptor;
import mtons.modules.lang.Const;
import mtons.modules.pojos.Page;
import mtons.modules.pojos.UserContextHolder;
import mtons.modules.pojos.UserProfile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.faxsun.core.persist.entity.LiveManagerPO;
import com.faxsun.core.persist.entity.LiveMsgPO;
import com.faxsun.core.persist.entity.LivePO;
import com.faxsun.core.persist.entity.UserPO;
import com.faxsun.core.persist.entity.WechatMsgPO;
import com.faxsun.core.service.LiveAdminService;
import com.faxsun.core.service.LiveMsgService;
import com.faxsun.core.service.UserService;
import com.faxsun.core.service.WechatService;
import com.faxsun.pojos.view.Live;
import com.faxsun.web.controller.FrontViewConstants;
import com.faxsun.web.endpoint.entity.ChannelJSON;
import com.faxsun.web.endpoint.entity.LiveMsgJSON;
import com.faxsun.web.endpoint.entity.LiveRangeData;
import com.faxsun.web.pojos.WechatUserInfo;
import com.faxsun.web.utils.MobileDetect;
import com.faxsun.web.utils.WechatApiUtils;

@Controller
@RequestMapping("/live")
public class LiveController extends BaseController {

	private static final Logger LOG = LoggerFactory.getLogger(LiveController.class);

	@Autowired
	protected WechatService wechatsService;

	@Autowired
	protected LiveMsgService liveMsgService;

	@Autowired
	protected LiveAdminService liveAdminService;

	@Autowired
	protected UserService userService;

	private static int MAX_RESULT = 10000;

	private Date newestId = null;
	private static final String dateAndTimeFormatter = "yyyy.MM.dd HH:mm:ss";

	@Value("${live.url.pattern}")
	private String host;

	@Autowired
	private WechatApiUtils wechatApiUtils;

	/**
	 * 非法访问关键字
	 */
	private static final String INVALID_ACCESS = "invalid";

	@RequestMapping(value = "/{topic}", method = RequestMethod.GET)
	public String timeline(@PathVariable String topic, ModelMap model, HttpServletRequest request) {
		// get timeline items
		Page page = wrapPage(1);
		page.setMaxResults(MAX_RESULT);

		List<WechatMsgPO> timelines = wechatsService.listRecent(page, topic);
		if (timelines == null || timelines.size() == 0) {
			timelines = Collections.emptyList();
		} else {
			newestId = timelines.get(0).getCreateTime();
		}
		model.addAttribute("timelines", timelines);
		model.addAttribute("topic", topic);
		model.addAttribute(FrontViewConstants.VIEW_META_TITLE, "范客生活 - " + topic.toUpperCase() + "直播");
		model.addAttribute(FrontViewConstants.VIEW_META_KEYWORD, "范客生活,直播," + topic);
		model.addAttribute("navigation", "live");

		String viewUrl = MobileDetect.getProperView(request, "/views/mobile/" + topic,
				FrontViewConstants.VIEW_LIVE_TIMELINE + topic);
		return viewUrl;
	}

	@RequestMapping(value = "/{topic}/checkAnyNew", method = RequestMethod.POST)
	@ResponseBody
	public boolean checkAnyNew(@PathVariable String topic, ModelMap model, HttpServletRequest request) {
		// get timeline items
		Page page = wrapPage(1);
		page.setMaxResults(MAX_RESULT);

		String qDateStr = request.getParameter("qDate");

		Date qDate = null;
		try {
			qDate = new SimpleDateFormat(dateAndTimeFormatter).parse(qDateStr);
		} catch (ParseException e) {
			e.printStackTrace();
			return false;
		}

		List<WechatMsgPO> timelines = wechatsService.listRecent(page, topic);
		if (timelines == null || timelines.size() == 0) {
			return false;
		} else {
			Date nId = timelines.get(0).getCreateTime();
			if (newestId == null) {
				newestId = nId;
			} else if (nId.compareTo(newestId) > 0) {
				newestId = nId;
			}

			if (qDate.compareTo(newestId) < 0) {
				return true;
			} else {
				return false;
			}
		}
	}

	/**
	 * 用于展示直播界面。需要完成用户的权限认证。
	 * 
	 * @return
	 */
	@RequestMapping(value = "/broadcast/{id}", method = RequestMethod.GET)
	public String broadcast(@PathVariable(value = "id") long id, ModelMap model, HttpServletRequest request) {
		String channelId = String.valueOf(id);
		UserProfile up = UserContextHolder.getUserProfile();
		if (up == null) {
			up = (UserProfile) session.getAttribute(Const.KEY_LOGIN);
		}

		if (liveMsgService.isValideChannelId(channelId) && up != null) {
			// 频道id合法
			// 加载用户角色

			Long channelid = Long.parseLong(channelId);
			LivePO channel = this.liveMsgService.findChannelById(channelid);
			model.addAttribute("channel", channel);

			Date start = channel.getStartTime();
			Date end = channel.getEndTime();

			Date current = new Date(System.currentTimeMillis());
			model.addAttribute("isLive", current.after(start) && current.before(end));

			LiveManagerPO po = this.liveAdminService.getLiveManager(up.getId(), channelid);
			if (po == null) {
				// 无直播权限
			} else {
				LOG.info("Userid=" + po.getId() + " ChannelId" + po.getLiveId() + " Role=" + po.getManagerRole());
				// ADMIN 或者 MANAGER
				model.addAttribute("role", po.getManagerRole());
			}

			// 加载最新的15条消息
			Page page = new Page(15);
			this.liveMsgService.listPage(page, channelid, 0L);

			model.addAttribute("msgs", page.getResults());

			// 用户是否关注公众号信息
			String openId = (String) session.getAttribute(LiveWechatInterceptor.KEY_OPENID);
			if (!org.springframework.util.StringUtils.isEmpty(openId)) {
				try {
					WechatUserInfo userInfo = wechatApiUtils.getUserInfo(openId);
					// 用户关注，则subcribe!=0
					model.addAttribute("isSubscribe", userInfo.getSubscribe() != 0);
				} catch (Exception e) {
					LOG.error("获取微信用户信息失败", e);
				}
			}

		} else {
			// 设置非法访问字段INVALID_ACCESS=invalid
			model.addAttribute(INVALID_ACCESS, Boolean.TRUE);
		}
		return FrontViewConstants.VIEW_MOBILE_LIVE_BROADCAST;
	}

	@RequestMapping(value = "/broadcastEdit/{id}", method = RequestMethod.GET)
	public String broadcastEdit(@PathVariable(value = "id") String channelId, ModelMap model) {
		UserProfile up = UserContextHolder.getUserProfile();
		if (up == null) {
			up = (UserProfile) session.getAttribute(Const.KEY_LOGIN);
		}

		if (liveMsgService.isValideChannelId(channelId) && up != null) {
			// 频道id合法
			// 加载用户角色

			Long channelid = Long.parseLong(channelId);
			LivePO channel = this.liveMsgService.findChannelById(channelid);
			model.addAttribute("channel", channel);

			LiveManagerPO po = this.liveAdminService.getLiveManager(up.getId(), channelid);
			if (po == null) {
				// 无直播权限
			} else {
				LOG.info("Userid=" + po.getId() + " ChannelId" + po.getLiveId() + " Role=" + po.getManagerRole());
				// ADMIN 或者 MANAGER
				String role = po.getManagerRole();
				model.addAttribute("role", role);

				if (!role.equals("ADMIN") && !role.equals("MANAGER")) {
					model.addAttribute(INVALID_ACCESS, Boolean.TRUE);
				}
			}

		} else {
			// 设置非法访问字段INVALID_ACCESS=invalid
			model.addAttribute(INVALID_ACCESS, Boolean.TRUE);
		}
		return FrontViewConstants.VIEW_MOBILE_LIVE_BROADCASTEDIT;
	}

	/**
	 * 创建频道视图，仅返回页面
	 * 
	 * @return
	 */
	@RequestMapping(value = "/createChannel", method = RequestMethod.GET)
	public String createView() {
		return FrontViewConstants.VIEW_MOBILE_LIVE_CREATE;
	}

	/**
	 * 修改频道视图，仅返回页面及实体
	 * 
	 * @param channelId
	 * @return
	 */
	@RequestMapping(value = "/modifyChannel/{id}", method = RequestMethod.GET)
	public String modifyView(@PathVariable(value = "id") String channelId, ModelMap model) {
		UserProfile up = UserContextHolder.getUserProfile();
		if (up == null) {
			up = (UserProfile) session.getAttribute(Const.KEY_LOGIN);
		}

		if (liveMsgService.isValideChannelId(channelId) && up != null) {
			// 频道id合法
			// 加载用户角色

			Long channelid = Long.parseLong(channelId);
			LivePO channel = this.liveMsgService.findChannelById(channelid);

			LiveManagerPO po = this.liveAdminService.getLiveManager(up.getId(), channelid);
			if (po == null) {
				// 无权限修改
				model.addAttribute(INVALID_ACCESS, Boolean.TRUE);
			} else {
				LOG.info("Userid=" + po.getId() + " ChannelId" + po.getLiveId() + " Role=" + po.getManagerRole());
				// ADMIN
				String role = po.getManagerRole();
				model.addAttribute("role", role);

				if (!role.equals("ADMIN")) {
					model.addAttribute(INVALID_ACCESS, Boolean.TRUE);
				} else {
					model.addAttribute("channel", channel);
				}
			}

		} else {
			// 设置非法访问字段INVALID_ACCESS=invalid
			model.addAttribute(INVALID_ACCESS, Boolean.TRUE);
		}
		return FrontViewConstants.VIEW_MOBILE_LIVE_MODIFY;
	}

	/**
	 * 微信外访问展示QRCode和频道信息的页面 前端需要判断channel是否为null，为null时，页面显示错误信息
	 * 
	 * @param channelId
	 * @param model
	 *            包含channel和url两个对象，channel中为频道信息，url为频道地址
	 * @return
	 */
	@RequestMapping(value = "/sharepage/{id}")
	public String sharePageOutOfWechat(@PathVariable(value = "id") Long channelId, ModelMap model) {
		LivePO channel = this.liveMsgService.findChannelById(channelId);
		model.addAttribute("channel", channel);
		if (channel != null) {
			String url = MessageFormat.format(this.host, channel.getId());
			model.addAttribute("url", url);
		}
		return FrontViewConstants.VIEW_MOBILE_LIVE_QRCODE_PAGE;
	}

	@RequestMapping(value = "/pcbroadcast/{channelId}/timeline", method = RequestMethod.GET)
	public String broadcastTimeline(@PathVariable Long channelId, ModelMap model, HttpServletRequest request) {
		LivePO livePo = wechatsService.findEventById(channelId);

		boolean valid = checkAdminForPC(livePo);

		if (!valid || livePo == null) {
			return FrontViewConstants.VIEW_404;
		}

		Page page = new Page();
		page.setMaxResults(MAX_RESULT);

		List<LiveMsgPO> timelines = liveMsgService.listNewMsg(page, channelId, 1);
		model.addAttribute("startMsgId", timelines.get(timelines.size() - 1).getId());

		if (timelines == null || timelines.size() == 0) {
			timelines = Collections.emptyList();
		}

		Collections.sort(timelines, LiveMsgPO.Comparators.DFLT_ID_DESC);
		List<LiveMsgJSON> tls = new ArrayList<LiveMsgJSON>(timelines.size());
		for (LiveMsgPO msg : timelines) {
			tls.add(LiveMsgJSON.parse(msg));
		}

		model.addAttribute("timelines", tls);
		Date now = new Date();
		if (now.after(livePo.getStartTime()) && now.before(livePo.getEndTime())) {
			model.addAttribute("checkAnyNew", "true");
		}
		List<LiveRangeData> lrds = convertLiveToRange(livePo);

		model.addAttribute("liveDateRange", lrds);

		model.addAttribute("live", livePo);

		model.addAttribute(FrontViewConstants.VIEW_META_TITLE, "范客直播 - " + livePo.getTopic());

		model.addAttribute(FrontViewConstants.VIEW_META_KEYWORD, "范客生活,直播," + livePo.getTopic());

		model.addAttribute("navigation", "live");

		model.addAttribute("ctx", request.getContextPath());

		LiveManagerPO liveManagerPO = this.liveAdminService.getLiveAdmin(livePo.getId());
		UserPO admin = this.userService.findUserPOBy(liveManagerPO.getUserId());
		model.addAttribute("liveAdmin", admin);

		String viewUrl = MobileDetect.getProperView(request, "/views/mobile/liveTimeline",
				FrontViewConstants.VIEW_LIVE_TIMELINE + "liveTimeline");
		return viewUrl;
	}

	@RequestMapping(value = "/pcbroadcast/{channelId}/bookpages/{page}", method = RequestMethod.GET)
	public String broadcastBookPage(@PathVariable Long channelId, @PathVariable Integer page, ModelMap model,
			HttpServletRequest request) {

		LivePO livePo = wechatsService.findEventById(channelId);
		if (livePo == null || livePo.getId() <= 4) {
			return FrontViewConstants.VIEW_404;
		}

		LiveManagerPO admin = liveAdminService.getLiveAdmin(channelId);
		boolean valid = checkAdminForPC(livePo);
		if (!valid || livePo == null) {
			return FrontViewConstants.VIEW_404;
		}
		UserPO userPO = userService.findUserPOBy(admin.getUserId());
		List<String> allPages = liveMsgService.getFinalBookPages(channelId, livePo, userPO);

		String data = allPages.get(page - 1);// convert to 0-based page

		String[] tmp = data.split(LiveMsgService.bookPageToken);
		if (tmp == null || tmp.length <= 0) {
			LOG.error("illegal data for live book:" + data + "with page:" + page);
			model.addAttribute("msgUrl", "http://www.faxsun.com/faxsun-info/src/img/wechatbarcode.png");
		} else {
			switch (tmp.length) {
			default:
			case 1:
				if (page == 1) {
					model.addAttribute("coverImg", tmp[0]);
				} else {
					String urlStr = tmp[0];
					if (urlStr.endsWith("jpg") || urlStr.endsWith("jpg!watermark")
					    || urlStr.endsWith("png") || urlStr.endsWith("png!watermark")
					    || urlStr.endsWith("gif") || urlStr.endsWith("gif!watermark")
						|| urlStr.endsWith("bmp") || urlStr.endsWith("bmp!watermark") ) {
						model.addAttribute("msgImg", "true");
					}
					model.addAttribute("msgUrl", urlStr);
				}
				break;
			case 2:
				// model.addAttribute("msgDate", tmp[0]);
				model.addAttribute("msgDesc", tmp[1]);
				break;
			case 4:
				model.addAttribute("msgDate", tmp[0]);
				model.addAttribute("msgText", tmp[1]);
				model.addAttribute("adminAvatar", tmp[2]);
				model.addAttribute("adminName", tmp[3]);
				break;
			case 5:
				model.addAttribute("msgTopic", tmp[0]);
				model.addAttribute("msgStartTime", tmp[1]);
				model.addAttribute("msgEndTime", tmp[2]);
				model.addAttribute("adminAvatar", tmp[3]);
				model.addAttribute("adminName", tmp[4]);
				break;
			}

		}

		model.addAttribute("pageNum", page);
		String viewUrl = FrontViewConstants.VIEW_LIVE_TIMELINE + "partials/liveBookPage";
		return viewUrl;
	}

	@RequestMapping(value = "/pcbroadcast/{channelId}/book", method = RequestMethod.GET)
	public String broadcastBook(@PathVariable Long channelId, ModelMap model, HttpServletRequest request) {

		LivePO livePo = wechatsService.findEventById(channelId);
		if (livePo == null || livePo.getId() <= 4) {
			return FrontViewConstants.VIEW_404;
		}

		LiveManagerPO admin = liveAdminService.getLiveAdmin(channelId);
		boolean valid = checkAdminForPC(livePo);
		if (!valid || livePo == null) {
			return FrontViewConstants.VIEW_404;
		}

		model.addAttribute("live", livePo);

		UserPO userPO = this.userService.findUserPOBy(admin.getUserId());
		List<String> allPages = liveMsgService.getFinalBookPages(channelId, livePo, userPO);

		model.addAttribute("msgSize", allPages.size());
		model.addAttribute("liveAdmin", userPO);

		model.addAttribute(FrontViewConstants.VIEW_META_TITLE, "范客直播 - " + livePo.getTopic());

		model.addAttribute(FrontViewConstants.VIEW_META_KEYWORD, "范客生活,直播," + livePo.getTopic());

		model.addAttribute("navigation", "live");

		String viewUrl = "/views/live/liveBook";
		return viewUrl;
	}

	@RequestMapping(value = "/pcbroadcast/{channelId}/checkAnyNew", method = RequestMethod.POST)
	@ResponseBody
	public boolean broadcastCheckAnyNew(@PathVariable Long channelId, @RequestParam Long startMsgId, ModelMap model,
			HttpServletRequest request) {
		LivePO livePo = wechatsService.findEventById(channelId);

		boolean valid = checkAdminForPC(livePo);

		if (!valid || livePo == null) {
			return false;
		}

		Page page = new Page();
		page.setMaxResults(2);

		List<LiveMsgPO> timelines = liveMsgService.listNewMsg(page, channelId, startMsgId);

		if (timelines == null || timelines.size() == 0) {
			return false;
		} else {
			Long nId = timelines.get(timelines.size() - 1).getId();
			if (nId > startMsgId) {
				return true;
			} else {
				return false;
			}
		}
	}

	/**
	 * 获取用户创建的直播
	 * 
	 * @return
	 */
	@RequestMapping(value = "/channels", method = RequestMethod.GET)
	public String getChannelsByUser(ModelMap model, HttpServletRequest request) {
		UserProfile up = UserContextHolder.getUserProfile();
		if (up == null) {
			return FrontViewConstants.VIEW_404;
		}
		List<Live> lives = liveAdminService.getMyLiveWithNop(up.getId());
		if (lives == null) {
			lives = Collections.emptyList();
		}
		model.addAttribute("lives", this.binningLives(lives));
		return FrontViewConstants.VIEW_MY_LIVES;
	}

	private HashMap<String, List<Live>> binningLives(List<Live> lives) {
		LinkedHashMap<String, List<Live>> binning = new LinkedHashMap<String, List<Live>>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Collections.sort(lives, new Comparator<Live>() {
			@Override
			public int compare(Live o1, Live o2) {
				if (o1.getStartTime().getTime() > o2.getStartTime().getTime()) {
					return -1;
				}
				if (o1.getStartTime().getTime() > o2.getStartTime().getTime()) {
					return 1;
				} else {
					return 0;
				}
			}

		});
		for (Live live : lives) {
			Date startDate = live.getStartTime();
			String dateStr = sdf.format(startDate);
			List<Live> dayLives = binning.get(dateStr);
			if (dayLives == null) {
				dayLives = new ArrayList<Live>();
				binning.put(dateStr, dayLives);
			}
			dayLives.add(live);
		}

		return binning;
	}

	private List<LiveRangeData> convertLiveToRange(LivePO livePO) {
		List<LiveRangeData> ret = new ArrayList<LiveRangeData>();
		List<Date> dates = liveMsgService.findMsgDateById(livePO.getId());
		for (Date d : dates) {
			LiveRangeData lrd = new LiveRangeData(d);
			ret.add(lrd);
		}
		/*
		 * Date startDate = livePO.getStartTime(); Date endDate =
		 * livePO.getEndTime();
		 * 
		 * Calendar c1 = Calendar.getInstance(); c1.setTime(startDate); Calendar
		 * c2 = Calendar.getInstance(); c2.setTime(endDate);
		 * 
		 * List<LiveRangeData> ret = new ArrayList<LiveRangeData>();
		 * 
		 * while(c1.getTime().before(c2.getTime())){ LiveRangeData lrd = new
		 * LiveRangeData(c2.getTime()); ret.add(lrd);
		 * c2.add(Calendar.DAY_OF_MONTH, -1); }
		 */
		return ret;
	}

	private boolean checkAdminForPC(LivePO livePo) {
		if (livePo != null) {
			return livePo.isSelected();
		}
		return Boolean.FALSE;
	}

	@RequestMapping(value = "/broadcastList")
	public String broadcastList(ModelMap model, HttpServletRequest request) {
		Page page = new Page();
		page.setMaxResults(Integer.MAX_VALUE);

		page = wechatsService.pagingAllEvent(page, false);
		@SuppressWarnings("unchecked")
		List<LivePO> all = (List<LivePO>) page.getResults();

		List<List<ChannelJSON>> ret = new LinkedList<List<ChannelJSON>>();
		TreeMap<String, List<ChannelJSON>> mappings = new TreeMap<String, List<ChannelJSON>>(
				ChannelJSON.Comparators.YEARMONTH_ASC);

		for (int i = 0; i < all.size(); i++) {
			LivePO livepo = (LivePO) all.get(i);
			boolean valid = checkAdminForPC(livepo);
			if (valid || livepo.getTopic().equals("cesasia2015") || livepo.getTopic().equals("turingphone2015")) {
				ChannelJSON cjson = ChannelJSON.build(livepo, request.getContextPath());
				String ymStr = cjson.getYearMonthString();
				List<ChannelJSON> monthList = mappings.get(ymStr);
				if (monthList == null) {
					monthList = new ArrayList<ChannelJSON>();
					mappings.put(ymStr, monthList);
				}
				monthList.add(cjson);
			}
		}

		for (Entry<String, List<ChannelJSON>> entry : mappings.entrySet()) {
			List<ChannelJSON> monthList = entry.getValue();
			ret.add(0, monthList);
		}

		model.addAttribute("navigation", "live");
		model.addAttribute("liveLists", ret);

		return "/views/live/broadcastList";
	}

}
